package org.dru.clay.rhino.feature.shell;

import org.dru.clay.rhino.feature.Feature;
import org.mozilla.javascript.*;

import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;

/**
 * Shell
 * User: joakimd
 * Date: 2013-07-18
 * Time: 15:56
 */
public final class Shell extends Feature {
    private static final String[] FUNCTION_NAMES = {
            "Shell_env",
            "Shell_exec"
    };

    @Override
    public void init(final Context context, final ScriptableObject scope) throws Exception {
        scope.defineFunctionProperties(FUNCTION_NAMES, Shell.class, ScriptableObject.DONTENUM);
        loadFeatureScript(context, scope, Shell.class);
    }

    public static Object Shell_env(final Context context, final Scriptable thisObj,
                                   final Object[] args, final Function funcObj) throws Exception {
        ScriptableObject result = (ScriptableObject) context.newObject(thisObj);
        for (final Map.Entry<String, String> entry : System.getenv().entrySet()) {
            result.defineProperty(entry.getKey(), entry.getValue(), ScriptableObject.CONST);
        }
        return result;
    }

    public static Object Shell_exec(final Context context, final Scriptable thisObj,
                                    final Object[] args, final Function funcObj) throws Exception {
        NativeArray array = (NativeArray) args[0];
        NativeObject object = (NativeObject) args[1];
        File dir = new File(Context.toString(args[2]));
        String[] commands = toStringArray(array.toArray());
        Collection<String> envp = new ArrayList<String>();
        for (final Object id : object.keySet()) {
            final String key = Context.toString(id);
            if (ScriptableObject.hasProperty(object, key)) {
                envp.add(key + "=" + getString(object, key));
            }
        }
        Runtime runtime = Runtime.getRuntime();
        Process process = runtime.exec(commands, envp.toArray(new String[envp.size()]), dir);
        final InputStream in;
        int res = process.waitFor();
        if (res == 0) {
            in = process.getInputStream();
        } else {
            in = process.getErrorStream();
        }
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        final byte[] buf = new byte[1024];
        int length;
        while ((length = in.read(buf)) != -1) {
            out.write(buf, 0, length);
        }
        in.close();
        if (res == 0) {
            return out.toString("utf-8");
        }
        else {
            throw ScriptRuntime.constructError("compile error", out.toString("utf-8"));
        }
    }
}
